package pos.utils;

import com.sun.j3d.utils.geometry.Text2D;
import java.awt.event.*;
import java.util.ArrayList;
import javax.media.j3d.*;
import javax.vecmath.*;

/**
 * 一个用java3d模拟的具有浮动Dock风格的单选工具条
 * @author plus
 */
public class Dock2D extends TransformGroup implements IContainer, Pickable, Invokeable{
    private final static int STATUE_RESIZING=1, STATUE_FIXED=2;
    private int currentStatue=STATUE_FIXED;
    private double progress=1;
    private ArrayList<ImageButton2D> subItems;
    private ArrayList<String> subItemTitles;
    private Text2D textItem;
    private Pickable currentItem,lastItem;
    private Transform3D myTransform;
    private IContainer myHost;
    private Vector3d pos;
    private float itemWidth,itemHeight, hotScale;
    
    /**
     * 构造函数，构造一个空的Dock
     * @param pos Dock左中点的坐标位置
     * @param itemWidth Dock内对象的宽度
     * @param itemHeight Dock内对象的高度
     * @param hotScale 当前热对象的放大倍数
     */
    public Dock2D(Vector3d pos, float itemWidth, float itemHeight, float hotScale) {
        this.pos = pos;
        this.itemWidth = itemWidth;
        this.itemHeight = itemHeight;
        this.hotScale = hotScale;
        myTransform = new Transform3D();
        myTransform.set(pos);
        textItem=new Text2D("             ",new Color3f(1f,1f,1f),"微软雅黑",
                (int)(itemHeight*500d),java.awt.Font.PLAIN);
        this.addChild(getTG(textItem,(float)pos.x,(float)pos.y-itemHeight*(1+itemHeight),(float)pos.z));
        this.setTransform(myTransform);
        this.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        subItems=new ArrayList<ImageButton2D>();
        subItemTitles=new ArrayList<String>();
    }

    /**
     * 往Dock内添加对象
     * @param item 需添加的对象
     * @return 当前Dock内的对象数
     */
    public int addSubItem(Pickable item) {
        item.setHost(this);
        subItems.add((ImageButton2D)item);
        this.addChild((TransformGroup)item);
        if (currentItem==null) lastItem=currentItem=item;
        updateDock();
        textItem.setString(subItemTitles.get(subItems.indexOf(currentItem)));
        return subItems.size();
    }
    /**
     * 往Dock内添加默认对象(ImageButton2D)的简便方法
     * @param imgKey 需添加对象图片路径在路径资源库中的键
     * @param colorIdle 需添加对象待命时的颜色叠加
     * @param colorHot 需添加对象选中时的颜色叠加
     * @param colorClicked 需添加对象触发时的颜色叠加
     * @param eventName 需添加对象触发时引起的事件名
     * @param title 需添加对象的标题
     * @return 当前Dock内的对象数
     */
    public int addSubItem( String imgKey, Color3f colorIdle, Color3f colorHot, 
            Color3f colorClicked, String eventName,String title) {
        ImageButton2D item=new ImageButton2D(new Vector3d(),itemWidth, itemHeight,
                imgKey,colorIdle,colorHot,colorClicked,eventName);
        subItemTitles.add(title);
        return addSubItem(item);
    }
    /**
     * 往Dock内添加默认对象(ImageButton2D)的简便方法
     * @param texture 需添加对象的材质
     * @param colorIdle 需添加对象待命时的颜色叠加
     * @param colorHot 需添加对象选中时的颜色叠加
     * @param colorClicked 需添加对象触发时的颜色叠加
     * @param eventName 需添加对象触发时引起的事件名
     * @param title 需添加对象的标题
     * @return 当前Dock内的对象数
     */
    public int addSubItem( Texture2D texture, Color3f colorIdle, Color3f colorHot,
            Color3f colorClicked, String eventName,String title) {
        ImageButton2D item=new ImageButton2D(new Vector3d(), itemWidth,itemHeight,
                texture,colorIdle,colorHot,colorClicked,eventName);
        subItemTitles.add(title);
        return addSubItem(item);
    }
    /**
     * 执行子对象发起的事件，不做处理的时间发回控制器处理
     * @param EventName 事件名。每个事件名绑定一个Command对象，对应的Command对象将被执行
     * @param Param 传递给对应Command的参数
     * @return 由对应Command的参数
     */
    public Object doEvent(String eventName, Object Param) {
        if (eventName.equals("SetHotItem")){
            refreshCurrentItem((Pickable)Param);
        }
        return myHost.doEvent(eventName, Param);
    }
    
    public void setCurrentItem(int itemID){
        refreshCurrentItem(this.subItems.get(itemID));
    }
    
    private void refreshCurrentItem(Pickable currentItem){
        if(this.currentItem.equals(currentItem)) return;    //仅当变化发生时更新
        lastItem=this.currentItem;
        this.currentItem=currentItem;
        for(int itemID=0; itemID<subItems.size();itemID++){
            if(!subItems.get(itemID).equals(currentItem)){
                subItems.get(itemID).setStatue(Pickable.Idle);
            }else
                subItems.get(itemID).setStatue(Pickable.Hot);
        }
        if (currentStatue==STATUE_FIXED)
            progress=0;
        else
            progress=(1-progress);
        currentStatue=STATUE_RESIZING;
        textItem.setString(subItemTitles.get(subItems.indexOf(currentItem)));
    }
    
    private void updateDock(){
        double offsetX=0;
        for(int itemID=0; itemID<subItems.size();itemID++){
            ImageButton2D currentButton=subItems.get(itemID);
            if(currentButton.equals(currentItem)){
                currentButton.setPosition(
                        new Vector3d(pos.x+offsetX+((hotScale-1)*progress)*0.15*itemWidth,pos.y,pos.z));
                currentButton.setScale(1+(hotScale-1)*progress);
                offsetX+=((1+(hotScale-1)*progress)*1.1*itemWidth);
                
            }else if(currentButton.equals(lastItem)){
                currentButton.setPosition(
                        new Vector3d(pos.x+offsetX+((hotScale-1)*(1-progress))*0.15*itemWidth,pos.y,pos.z));
                currentButton.setScale(1+(hotScale-1)*(1-progress));
                offsetX+=((1+(hotScale-1)*(1-progress))*1.1*itemWidth);
                
            }else{
                currentButton.setPosition(
                        new Vector3d(pos.x+offsetX,pos.y,pos.z));
                currentButton.setScale(1);
                offsetX+=(1.2*itemWidth);
            }
            //System.err.println(offsetX);
        }
    }
    /**
     * 处理键盘事件
     * @param evt 待处理的键盘事件
     */
     public void processKeyEvent(KeyEvent evt) {
        if (evt.getID()==KeyEvent.KEY_RELEASED){
            //System.err.println(evt.getKeyCode());
            switch(evt.getKeyCode()){
                case KeyEvent.VK_LEFT:
                    preItem();
                    break;
                case KeyEvent.VK_RIGHT:
                    nextItem();
                    break;
            }
        }
    }

    private void nextItem(){
        int nextItemID=(subItems.indexOf(currentItem)+1)%subItems.size();
        System.err.println(nextItemID);
        refreshCurrentItem(subItems.get(nextItemID));
    }
    private void preItem(){
        int nextItemID=(subItems.indexOf(currentItem)-1);
        if (nextItemID<0) nextItemID+=subItems.size();
        System.err.println(nextItemID);
        refreshCurrentItem(subItems.get(nextItemID));
    }
    
    private static TransformGroup getTG(Text2D child,float x,float y,float z){
        Transform3D transRes = new Transform3D();                                
        transRes.set(new Vector3f(x, y, z));
        Transform3D transText=new Transform3D();
        transText.setScale(0.25);
        transRes.mul(transText);
        TransformGroup TGRes = new TransformGroup(transRes);
        if (child!=null) {
            ((Appearance)child.getAppearance()).setCapability(Appearance.ALLOW_TEXTURE_WRITE);
            TGRes.addChild(child);
        }
        return TGRes;
    }
    
    /**
     * 为条件调用器调用的方法
     * @param Step 条件调用器送回的步进值
     */
    public void invoke(double Step) {
        if (currentStatue==STATUE_RESIZING){
            progress+=Step;
            if(progress>=1){
                currentStatue=STATUE_FIXED;
                progress=1;
            }
            updateDock();
        }
    }

    /**
     * 为鼠标拾取行为调用的方法
     * @param evt 拾取当此对象的鼠标事件
     * @deprecated 现在直接由Dock中的对象处理拾取方法
     */
    public void picked(MouseEvent evt) {
    }

    /**
     * 设置此Dock的拥有容器
     * @param host 拥有容器
     */
    public void setHost(IContainer host) {
        myHost=host;
    }
    /**
     * 设置Dock当前在容器中的状态(待命||选中||触发)
     * @param statue Dock当前在容器中的状态
     */
    public void setStatue(int statue) {
        this.currentItem.setStatue(statue);
    }

}
